<!--
 * @Author: wei
 * @description: 大屏自适应容器组件
 * @LastEditTime: 2022-09-09 16:42:40
-->
<template>
	<!-- <section class="screen-box" :style="boxStyle"> -->
	<div class="screen-wrapper" ref="screenWrapper" :style="wrapperStyle">
		<slot></slot>
	</div>
	<!-- </section> -->
</template>
<script>
/**
 * 防抖函数
 * @param {T} fn
 * @param {number} delay
 * @return
 */
function debounce(fn, delay) {
	let timer = null
	return function (...args) {
		timer = setTimeout(
			() => {
				typeof fn === 'function' && fn.apply(null, args)
				clearTimeout(timer)
			},
			delay > 0 ? delay : 100
		)
	}
}

export default {
	name: 'VScaleScreen',
	props: {
		width: {
			type: [String, Number],
			default: 1920
		},
		height: {
			type: [String, Number],
			default: 1080
		},
		fullScreen: {
			type: Boolean,
			default: false
		},
		autoScale: {
			type: [Object, Boolean],
			default: true
		},
		selfAdaption: {
			type: Boolean,
			default: true
		},
		delay: {
			type: Number,
			default: 500
		},
		boxStyle: {
			type: Object,
			default: () => ({})
		},
		wrapperStyle: {
			type: Object,
			default: () => ({})
		}
	},
	data() {
		return {
			currentWidth: 0,
			currentHeight: 0,
			originalWidth: 0,
			originalHeight: 0,
			onResize: null,
			observer: null
		}
	},
	watch: {
		selfAdaption(val) {
			if (val) {
				this.resize()
				this.addListener()
			} else {
				this.clearListener()
				this.clearStyle()
			}
		}
	},
	computed: {
		screenWrapper() {
			return this.$refs['screenWrapper']
		}
	},
	methods: {
		initSize() {
			return new Promise((resolve, reject) => {
				// console.log("初始化样式");
				//给父元素设置 overflow:hidden
				this.screenWrapper.parentNode.style.overflow = 'hidden'
				this.screenWrapper.parentNode.scrollLeft = 0
				this.screenWrapper.parentNode.scrollTop = 0

				this.$nextTick(() => {
					// region 获取大屏真实尺寸
					if (this.width && this.height) {
						this.currentWidth = this.width
						this.currentHeight = this.height
					} else {
						this.currentWidth = this.screenWrapper.clientWidth
						this.currentHeight = this.screenWrapper.clientHeight
					}
					// endregion
					// region 获取画布尺寸
					if (!this.originalHeight || !this.originalWidth) {
						this.originalWidth = window.screen.width
						this.originalHeight = window.screen.height
					}
					// endregion
					resolve()
				})
			})
		},
		updateSize() {
			if (this.currentWidth && this.currentHeight) {
				this.screenWrapper.style.width = `${this.currentWidth}px`
				this.screenWrapper.style.height = `${this.currentHeight}px`
			} else {
				this.screenWrapper.style.width = `${this.originalWidth}px`
				this.screenWrapper.style.height = `${this.originalHeight}px`
			}
		},
		handleAutoScale(scale) {
			if (!this.autoScale) return
			const screenWrapper = this.screenWrapper
			const domWidth = screenWrapper.clientWidth
			const domHeight = screenWrapper.clientHeight
			const currentWidth = document.body.clientWidth
			const currentHeight = document.body.clientHeight
			screenWrapper.style.transform = `scale(${scale},${scale}) `
			let mx = Math.max((currentWidth - domWidth * scale) / 2, 0)
			let my = Math.max((currentHeight - domHeight * scale) / 2, 0)
			if (typeof this.autoScale === 'object') {
				// @ts-ignore
				!this.autoScale.x && (mx = 0)
				// @ts-ignore
				!this.autoScale.y && (my = 0)
			}
			// console.log({
			//   mx,
			//   my,
			//   currentWidth,
			//   currentHeight,
			//   domWidth,
			//   domHeight,
			//   scale,
			// });
			this.screenWrapper.style.margin = `${my}px ${mx}px`
		},
		updateScale() {
			const screenWrapper = this.screenWrapper
			// 获取真实视口尺寸
			const currentWidth = document.body.clientWidth
			const currentHeight = document.body.clientHeight
			// 获取大屏最终的宽高onResize
			const realWidth = this.currentWidth || this.originalWidth
			const realHeight = this.currentHeight || this.originalHeight
			// 计算缩放比例
			const widthScale = currentWidth / realWidth
			const heightScale = currentHeight / realHeight
			// console.log({currentWidth, currentHeight,realWidth,realHeight});

			// 若要铺满全屏，则按照各自比例缩放
			if (this.fullScreen) {
				screenWrapper.style.transform = `scale(${widthScale},${heightScale})`
				return false
			}
			// 按照宽高最小比例进行缩放
			const scale = Math.min(widthScale, heightScale)
			this.handleAutoScale(scale)
		},
		initMutationObserver() {
			const screenWrapper = this.screenWrapper
			const observer = (this.observer = new MutationObserver(() => {
				this.onResize()
			}))

			observer.observe(screenWrapper, {
				attributes: true,
				attributeFilter: ['style'],
				attributeOldValue: true
			})
		},
		clearListener() {
			window.removeEventListener('resize', this.onResize)
		},
		addListener() {
			window.addEventListener('resize', this.onResize)
		},
		clearStyle() {
			// console.log("清除");
			const screenWrapper = this.screenWrapper
			screenWrapper.parentNode.style.overflow = 'auto'

			screenWrapper.style = ''
		},
		async resize() {
			if (!this.selfAdaption) {
				return
			}
			await this.initSize()
			this.updateSize()
			this.updateScale()
		}
	},
	mounted() {
		this.onResize = debounce(() => {
			this.resize()
		}, this.delay)
		this.$nextTick(() => {
			if (this.selfAdaption) {
				this.resize()
				this.addListener()
			}
		})
	},
	beforeDestroy() {
		this.clearListener()
		// this.observer.disconnect()
	}
}
//
</script>

<style scoped>
.screen-box {
	overflow: hidden;
	background-size: 100% 100%;
	background: #000;
	width: 100vw;
	height: 100vh;
}

.screen-wrapper {
	transition-property: all;
	transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	transition-duration: 500ms;
	position: relative;
	overflow: hidden;
	z-index: 100;
	transform-origin: left top;
}
</style>
